home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- static char sccsid[] = "@(#)atalkad.c 1.2 (Stanford) 9/87";
- #endif
-
- /*
- * Appletalk administration daemon.
- *
- * Answers request packets from client appletalk gateways by supplying
- * the appletalk-to-ip network configuration table and the local
- * appletalk gateway configuration information.
- */
-
- /*
- * (C) 1986, Stanford Univ. CSLI.
- * May be used but not sold without permission.
- */
-
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <sys/file.h>
- #include <sys/time.h>
- #include <netinet/in.h>
- #define iaddr_t long
- #include "gwctl.h"
- #include "ab.h"
-
- #include <signal.h>
- #include <stdio.h>
- #include <strings.h>
- #include <errno.h>
- #include <ctype.h>
- #include <netdb.h>
-
- /* for 4.2 systems */
- #ifndef FD_SETSIZE
- # define FD_SETSIZE sizeof(int)*8
- # define NFDBITS sizeof(int)*8
- # define howmany(x,y) (1)
- # define FD_SET(n, p) (p)->fds_bits[0] |= (1<<(n))
- # define FD_CLR(n, p) (p)->fds_bits[0] &= ~(1<<(n))
- # define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n)))
- # define FD_ZERO(p) bzero((char *)p, sizeof(*p))
- #endif
-
- #ifndef ATALKATAB
- #define ATALKATAB "/etc/atalkatab"
- #endif
- #ifndef ATALKALOG
- #define ATALKALOG "/usr/adm/atalkalog"
- #endif
- #ifndef ATALKAPID
- #define ATALKAPID "/usr/adm/atalkapid"
- #endif
-
- int debug;
- extern int errno;
- struct sockaddr_in sin = { AF_INET };
- int s; /* socket fd */
- struct sockaddr_in fsin; /* foreign sockaddr_in */
- int fsinlen;
- int sig, sigint(), sighup();
- struct aaconf aa; /* receive packet */
- struct aaconf aas; /* send packet */
- struct timeval tvwait; /* timer for select */
-
- /* Mask of high 3 bytes of a network address */
- iaddr_t node_mask;
-
- /*
- * Globals below are associated with the atalka database file (atalkatab).
- */
- char *atalkatab = ATALKATAB;
- char *atalkalog = ATALKALOG;
- char *atalkapid = ATALKAPID;
- FILE *fp;
- char line[256]; /* line buffer for reading atalkatab */
- char *linep; /* pointer to 'line' */
- int linenum; /* current line number in atalkatab */
-
- #define NANETS 64 /* max number of 'anets' structs */
-
- struct anets {
- u_short net; /* atalk net */
- u_char flags; /* flags, see aroute* in gwctl.h */
- u_char confsize; /* size of databytes in conf below */
- iaddr_t iaddr; /* ip address */
- char zone[32]; /* zone name */
- char conf[64]; /* configuration info, if kbox */
- } anets[NANETS];
-
- /* Internal format of conf structure */
- struct conf {
- iaddr_t ipbroad; /* broadcast addr on ether */
- iaddr_t ipname; /* address of name server */
- iaddr_t ipdebug; /* address of debug host */
- iaddr_t ipfile; /* address of file server */
- u_long ipother[4]; /* other addresses passed via IPGP */
- #define ipsmask anetet /* old use for this field */
- u_short anetet; /* ethertalk net number of enet */
- #define ipsshift startddpWKSUnix /* old: subnet shift (unused) */
- u_short startddpWKSUnix; /* start of unix WKS udp ports */
- u_long flags; /* various bit flags */
- #define conf_stayinzone 0x1 /* no looking at other zones */
- #define conf_laserfilter 0x2 /* NBP filtering for LaserWriters */
- #define conf_tildefilter 0x4 /* NBP filtering, "name~" */
- u_short ipstatic; /* number of static IP addrs */
- u_short ipdynamic; /* number of dynamic IP addrs */
- u_short atneta; /* atalk net #, appletalk */
- u_short atnete; /* atalk net #, ethernet */
- } conf_proto;
-
- int nanets; /* current number of anets */
- long modtime; /* last modification time of atalkatab */
- long size; /* last known size of file */
- char aroutes[512]; /* route tuples built by buildart() */
- int arouteslen;
- char azones[512]; /* zone table built by buildzone() */
- int azoneslen;
-
- int scanonly = 0;
-
-
- usage()
- {
- printf("usage: atalkad [-c filename] [-debug] [route|boot|exit]\n");
- printf("usage: -c means check file\n");
- exit(1);
- }
-
- main(argc, argv)
- char *argv[];
- {
- register int n;
- FILE *filep;
- int pid;
-
- for (argc--, argv++ ; argc > 0 ; argc--, argv++) {
- if (argv[0][0] == '-') {
- switch (argv[0][1]) {
- case 'd':
- debug++;
- break;
- case 'c':
- if (argv[0][2]) {
- atalkatab = argv[0]+2;
- } else if (argc > 1 && argv[1]) {
- atalkatab = argv[1];
- argc--, argv++;
- }
- scanonly++;
- break;
- default:
- usage();
- }
- continue;
- }
- if (scanonly)
- usage();
- if (strcmp(argv[0], "boot") == 0)
- sig = SIGINT;
- else if (strcmp(argv[0], "route") == 0)
- sig = SIGHUP;
- else if (strcmp(argv[0], "exit") == 0)
- sig = SIGKILL;
- else
- usage();
- if ((filep = fopen(atalkapid, "r")) == NULL
- || fscanf(filep, "%d", &pid) != 1
- || kill(pid, sig) < 0) {
- printf("failed to send signal to daemon\n");
- exit(1);
- } else {
- printf("sent signal to daemon\n");
- exit(0);
- }
- }
-
- if (scanonly) {
- readtab();
- dumptab();
- exit(0);
- }
-
- if (debug == 0) {
- int t, f;
- if (fork())
- exit(0);
- for (f = 0; f < 10; f++)
- (void) close(f);
- (void) open("/", 0);
- (void) dup2(0, 1);
- (void) dup2(0, 2);
- t = open("/dev/tty", 2);
- if (t >= 0) {
- ioctl(t, TIOCNOTTY, (char *)0);
- (void) close(t);
- }
- }
-
- log("### ATALKA daemon starting");
- pid = getpid();
- if ((filep = fopen(atalkapid, "w")) == NULL) {
- log("couldnt create pid file %s\n", atalkapid);
- exit(1);
- }
- fprintf(filep, "%d", pid);
- fclose(filep);
- signal(SIGHUP, sighup);
- signal(SIGINT, sigint);
-
- while ((s = socket(AF_INET, SOCK_DGRAM, 0, 0)) < 0) {
- log("socket call failed");
- sleep(5);
- }
- sin.sin_port = htons(aaPort);
- if (bind(s, (caddr_t)&sin, sizeof (sin), 0) < 0) {
- log("bind call failed");
- exit(1);
- }
-
- /* fill in node mask in a machine independent manner */
- node_mask = inet_addr("255.255.255.0");
-
- readtab();
- for (;;) {
- fsinlen = sizeof (fsin);
- n = recvfrom(s, (caddr_t)&aa, sizeof aa,
- 0, (caddr_t)&fsin, &fsinlen);
- if (n < 0) {
- if (errno != EINTR) {
- log("recv failed");
- exit(1);
- }
- readtab();
- sendall(sig);
- continue;
- }
- if (n < aaconfMinSize || ntohl(aa.magic) != aaMagic)
- continue;
- readtab();
- sendreply();
- }
- }
-
-
- /*
- * Interrupts are used to signal type of sendall().
- */
- sighup() { sig = aaROUTEI; }
- sigint() { sig = aaRESTART; }
-
-
- /*
- * Send reply to packet aa.
- */
- sendreply()
- {
- register struct anets *an;
- register n;
-
- switch (aa.type) {
- case aaCONF:
- for (an = &anets[0], n = 0 ; n < nanets ; an++, n++)
- if (an->iaddr == aa.ipaddr && an->confsize &&
- (an->flags & arouteKbox) &&
- (an->flags & arouteEtalk) == 0)
- goto found;
- log("aaCONF from %s ***** not in table", inet_ntoa(aa.ipaddr));
- return;
- found:
- log("aaCONF to %s", inet_ntoa(aa.ipaddr));
- n = an->confsize;
- bcopy(an->conf, aa.stuff, n);
- break;
- case aaZONE:
- log("aaZONE to %s", inet_ntoa(aa.ipaddr));
- n = azoneslen;
- bcopy(azones, aa.stuff, n);
- break;
- case aaZONEQ:
- log("aaZONEq from %s", inet_ntoa(aa.ipaddr));
- if ((n = zipinput()) <= 0)
- return; /* drop */
- break;
- case aaROUTEI:
- log("aaROUTEI to %s", inet_ntoa(aa.ipaddr));
- n = arouteslen;
- bcopy(aroutes, aa.stuff, n);
- break;
- default:
- /* don't reply here! */
- return;
- }
- aa.count = htons(n);
- sendto(s, (caddr_t)&aa, aaconfMinSize + n, 0,
- &fsin, sizeof fsin);
- }
-
-
- char *
- netstring(n)
- u_short n;
- {
- int net;
- static char mynetstr[30];
-
- net = ntohs(n);
- sprintf(mynetstr, "%d.%d", (net>>8) & 0xff, net & 0xff);
- return(mynetstr);
- }
-
- /*
- * return pointer to zone name
- * NULL if none
- */
- char *
- zoneof(net)
- u_short net;
- {
- register struct anets *an;
- int n;
-
- for (an = &anets[0], n=0 ; n < nanets ; an++, n++)
- if (net == an->net)
- return(an->zone);
- return(NULL);
- }
-
- /*
- * return a value that is always printable
- *
- */
- char *
- pzoneof(net)
- u_short net;
- {
- char *p = zoneof(net);
- return(p == NULL ? "unknown" : p);
- }
-
- dumptab()
- {
- register struct anets *an;
- register n, size;
- char *hostnameof();
- struct conf *conf;
- iaddr_t rs, re;
-
- size = 0;
- for (an = &anets[0], n = 0 ; n < nanets ; an++, n++) {
- printf("Route %s %s, ", netstring(an->net), an->zone);
- if ((an->flags & arouteKbox) && (an->flags & arouteEtalk) == 0)
- printf(" Kinetics box");
- if (an->flags & arouteCore)
- printf(" core gateway");
- if (an->flags & arouteHost)
- printf(" host is redirector");
- if (an->flags & arouteNet)
- if (an->flags & arouteBMask)
- printf(" net %d", an->flags & arouteBMask);
- else
- printf(" net 0: host is client");
- if ((an->flags & (arouteKbox|arouteEtalk)) == (arouteKbox|arouteEtalk))
- printf(" EtherTalk");
- printf(" at %s", hostnameof(an->iaddr));
- putchar('\n');
- if ((an->flags & arouteKbox) && (an->flags & arouteEtalk) == 0) {
- conf = (struct conf *)an->conf;
- printf("\tIP Broadcast: %s, ", inet_ntoa(conf->ipbroad));
- if (conf->ipname == conf->ipdebug) {
- printf("IP name and debug: %s\n", hostnameof(conf->ipname));
- printf("\tIP file server (unused)", hostnameof(conf->ipfile));
- } else {
- printf("IP name: %s\n",hostnameof(conf->ipname));
- printf("\tIP debug %s, ", hostnameof(conf->ipdebug));
- printf("IP file server (unused)", hostnameof(conf->ipfile));
- }
- if (ntohl(conf->flags) & conf_stayinzone)
- printf(", marked stay in zone");
- if (ntohl(conf->flags) & conf_laserfilter)
- printf(", laserwriters stay in zone");
- if (ntohl(conf->flags) & conf_tildefilter)
- printf(", tilde marked names stay in zone");
- putchar('\n');
- if (conf->startddpWKSUnix == htons(defddpWKSUnix))
- printf("\tUDP Port range for WKS starts at %d (old range)\n",
- defddpWKSUnix);
- else
- printf("\tUDP Port range for WKS starts at %d\n",
- ntohs(conf->startddpWKSUnix));
- #ifdef SHORTFORMAT
- if (conf->ipstatic)
- printf("\t%d ", ntohs(conf->ipstatic));
- else
- printf("\tNo");
- printf(" static ip addresses, ");
- if (conf->ipdynamic)
- printf("\t%d ", ntohs(conf->ipdynamic));
- else
- printf("\tNo");
- printf(" dynamic ip addresses\n");
- #else
- if (conf->ipstatic) {
- re = rs = ntohl(an->iaddr)+1;
- re += (ntohs(conf->ipstatic)-1);
- printf("\tIP static address range: %s",
- inet_ntoa(htonl(rs)));
- printf(" %s\n",inet_ntoa(htonl(re)));
- } else {
- printf("\tIP static address range: empty\n");
- re = ntohl(an->iaddr);
- }
- if (conf->ipdynamic) {
- re = rs = re+1;
- re += (ntohs(conf->ipdynamic)-1);
- printf("\tIP dynamic address range: %s",
- inet_ntoa(htonl(rs)));
- printf(" %s\n",inet_ntoa(htonl(re)));
- } else {
- printf("\tIP dynamic address range: empty\n");
- re = ntohl(an->iaddr);
- }
-
- #endif
- printf("\tKbox interfaces:\n");
- printf("\t\tlocaltalk: %s zone %s\n", netstring(conf->atneta),
- pzoneof(conf->atneta));
- printf("\t\tKIP: %s zone %s\n", netstring(conf->atnete),
- pzoneof(conf->atnete));
- if (conf->anetet) {
- printf("\t\tEtherTalk: %s zone %s\n", netstring(conf->anetet),
- pzoneof(conf->anetet));
- }
- }
- }
- }
-
- /*
- * Build arouteTuple's into area provided by caller.
- * Return byte count of tuples deposited.
- */
- buildart(at, maxsize)
- register struct arouteTuple *at;
- int maxsize;
- {
- register struct anets *an;
- register n, size;
-
- size = 0;
- for (an = &anets[0], n = 0 ; n < nanets ; an++, n++, at++) {
- size += sizeof *at;
- at->node = an->iaddr;
- at->net = an->net;
- at->flags = an->flags;
- at->hops = 0; /* start at one - incremented in gateway */
- }
- log("art build: %d entries, %d maximum",
- size/(sizeof(struct arouteTuple)),
- maxsize/(sizeof(struct arouteTuple)));
- if (size > maxsize)
- log("art build: routing table too big!!");
- if (size > (maxsize - 10) )
- log("art build: routing table size %d is near maximum of %d",
- size, maxsize );
- return (size);
- }
-
-
- #define MAXZ 32
-
- /*
- * Build zones structure to be returned by aaZONE.
- */
- buildzones(az, azlen)
- char *az;
- int azlen;
- {
- char zname[MAXZ][33];
- int nzname = 0;
- char netzone[NANETS];
- register i, iz, n;
- register char *cp;
- int zonenamelen = 0;
-
- /* make a pass thru anets, finding all unique zone names. */
-
- for (i = 0 ; i < nanets ; i++) {
- for (iz = 0 ; iz < nzname ; iz++)
- if (strcmp(anets[i].zone, zname[iz]) == 0)
- goto found;
- /* not found, make a new name */
- strcpy(zname[iz], anets[i].zone);
- zonenamelen += strlen(zname[iz]) + 1;
- netzone[i] = iz;
- nzname++;
- continue;
- /* found it, note the zname index */
- found:
- netzone[i] = iz;
- }
- /*
- * Build structure to send to gateway. Looks like:
- * net# net# ... 0 zonename
- * net# net# ... 0 zonename
- * 0xFFFF.
- */
- cp = az;
- for (iz = 0 ; iz < nzname ; iz++) {
- for (i = 0 ; i < nanets ; i++) {
- if (netzone[i] != iz)
- continue;
- /* anets[].net has been swapped by readtab */
- *cp++ = (ntohs(anets[i].net) >> 8);
- *cp++ = ntohs(anets[i].net);
- }
- *cp++ = 0; *cp++ = 0;
- *cp++ = n = strlen(zname[iz]);
- bcopy(zname[iz], cp, n);
- cp += n;
- }
- *cp++ = 0xFF; *cp++ = 0xFF;
- n = cp - az; /* length of table */
- if (n > sizeof(azones)) {
- log("buildzones: ZIP table too large");
- log("buildzones: don't worry if you are using a KIP later than 1/88");
- } else if (n > (sizeof(azones)-10))
- log("buildzones: ZIP table size %d approaching maximum of %d",
- n, sizeof(azones));
- log("zone names take %d bytes in gateway");
- return (n);
- }
-
-
- /*
- * Send aaRESTART or aaROUTEI to all gateways.
- */
- sendall(sig)
- {
- register struct anets *an;
- register n;
- int trys, count, rcount;
- fd_set fds;
- struct sockaddr_in tsin;
-
- tsin = sin;
- log("sendall(%s)", sig == aaRESTART ? "aaRESTART" : "aaROUTEI");
- aas.magic = htonl(aaMagic); /* setup send packet */
- aas.type = sig;
- aas.flags = 0;
- if (sig == aaROUTEI) {
- bcopy(aroutes, aas.stuff, arouteslen);
- count = arouteslen;
- } else {
- count = 0;
- }
- aas.count = htons(count);
- count += aaconfMinSize;
- /*
- * send to each kbox in the table.
- */
- for (an = &anets[0], n = 0 ; n < nanets ; an++, n++) {
- if ((an->flags & arouteKbox) == 0 || (an->flags & arouteEtalk))
- continue;
- trys = 0;
- tsin.sin_addr.s_addr = an->iaddr;
- sendto(s, (caddr_t)&aas, count, 0, &tsin, sizeof tsin);
- /*
- * receive until we get a good reply or timeout.
- */
- for (;;) {
- FD_ZERO(&fds);
- FD_SET(s, &fds);
- tvwait.tv_sec = 2; /* select waits 2 seconds */
- tvwait.tv_usec = 0;
- if (select(NFDBITS, &fds, 0, 0, &tvwait) != 1) {
- /* timeout */
- if (++trys < 4) {
- sendto(s, (caddr_t)&aas,
- count, 0, &tsin, sizeof tsin);
- continue;
- }
- log("no response from %s",
- inet_ntoa(an->iaddr));
- break;
- }
- fsinlen = sizeof fsin;
- rcount = recvfrom(s, (caddr_t)&aa, sizeof aa,
- 0, (caddr_t)&fsin, &fsinlen);
- if (rcount < 0) {
- if (errno == EINTR)
- continue;
- log("recv failed");
- exit(1);
- }
- if (rcount < aaconfMinSize
- || ntohl(aa.magic) != aaMagic)
- continue;
- if (aa.ipaddr != an->iaddr) {
- sendreply();
- continue;
- }
- /* our request got thru! */
- sendreply();
- break;
- }
- }
- log("sendall(%s) complete",sig==aaRESTART ? "aaRESTART" : "aaROUTEI");
- }
-
- /*
- * check over configurations
- *
- */
- checkconfigs()
- {
- int i;
- struct anets *an;
- struct conf *cp;
- int rangestart = 0;
- int rangeconflict = 0;
- int badrange = 0;
-
- for (an = anets, i = 0; i < nanets; i++, an++) {
- if (an->confsize >= sizeof(struct conf)) {
- cp = (struct conf *)an->conf;
- if (!cp->startddpWKSUnix) {
- cp->startddpWKSUnix = htons(defddpWKSUnix);
- if (rangestart) {
- if (rangestart != cp->startddpWKSUnix)
- rangeconflict = 1;
- } else rangestart = cp->startddpWKSUnix;
- } else {
- if (rangestart) {
- if (rangestart != cp->startddpWKSUnix)
- rangeconflict = 1;
- } else rangestart = cp->startddpWKSUnix;
- }
- }
- }
- rangestart = ntohs(rangestart);
- if (rangeconflict)
- log("Conflict in UDP WKS range start!");
- else if (rangestart != 200 && rangestart != defddpWKSUnix) {
- log("WARNING - UDP WKS range start %d is non-standard",
- ntohs(rangestart));
- }
- }
-
- /*
- * Read atalkatab database file. Avoid rereading the file if the
- * write date hasnt changed since the last time we read it.
- */
- readtab()
- {
- struct stat sbuf1, sbuf;
- register char *sp, *cpp;
- int v;
- register i;
- char st[128], *cp;
- register struct anets *an;
- iaddr_t iaddr;
-
- if (fp == 0) {
- if ((fp = fopen(atalkatab, "r")) == NULL) {
- log("can't open %s", atalkatab);
- exit(1);
- }
- }
- if (fstat(fileno(fp), &sbuf1) < 0)
- goto reopen;
- if (stat(atalkatab, &sbuf) < 0)
- goto reopen;
- if (sbuf1.st_dev == sbuf.st_dev && /* different... */
- sbuf1.st_ino == sbuf.st_ino && /* ...file */
- sbuf1.st_size == size && /* nec? */
- sbuf.st_size == size &&
- sbuf1.st_mtime == modtime && /* nec? */
- sbuf.st_mtime == modtime)
- return;
- reopen:
- if (fp)
- fclose(fp);
- if ((fp = fopen(atalkatab, "r")) == NULL) {
- log("can't open %s", atalkatab);
- exit(1);
- }
- fstat(fileno(fp), &sbuf);
- log("(re)reading %s", atalkatab);
- modtime = sbuf.st_mtime;
- size = sbuf.st_size;
- nanets = 0;
- an = &anets[-1];
- linenum = 0;
-
- /*
- * read and parse each line in the file.
- */
- for (;;) {
- if (fgets(line, sizeof line, fp) == NULL)
- break; /* done */
- if ((i = strlen(line)))
- line[i-1] = 0; /* remove trailing newline */
- linep = line;
- linenum++;
- if (line[0] == '#' || line[0] == 0)
- continue; /* skip comment lines */
- if (line[0] == ' ' || line[0] == '\t')
- goto confinfo;
- /*
- * lines not beginning with white space
- * represent a new net #
- */
- if (++nanets > NANETS) {
- log("'anets' table length exceeded");
- exit(1);
- }
- an++;
- cp = an->conf; /* store following lines here */
- an->confsize = 0;
- getfield(st, sizeof st);
- an->net = htons(getashort(st));
- getfield(st, sizeof st);
- i = 0;
- /* parse flags */
- for (cpp = st ; *cpp ; cpp++) {
- if (isupper(*cpp))
- *cpp = tolower(*cpp);
- switch (*cpp) {
- case 'c':
- i |= arouteCore; break;
- case 'k':
- i |= arouteKbox; break;
- case 'h':
- i |= arouteHost; break;
- case 'n':
- i |= arouteNet; break;
- case 'e':
- i |= (arouteEtalk|arouteKbox); break;
- case '0': case '1': case '2': case '3':
- i |= (*cpp - '0'); break;
- default:
- log("bad switch %s, linenum %d", st, linenum);
- }
- }
- an->flags = i;
- getfield(st, sizeof st);
- an->iaddr = getiaddr(st);
- getfield(an->zone, sizeof(an->zone));
- continue;
- confinfo:
- /*
- * lines beginning with white space
- * are configuration data for gateway.
- */
- for (;;) { /* for each field in line */
- int len;
- getfield(st, sizeof st);
- sp = st;
- if (*sp == 0)
- break;
- if (isupper(*sp))
- *sp = tolower(*sp);
- switch (*sp++) {
- case '%':
- /* escape code, one of 'n' */
- if (isupper(*sp))
- *sp = tolower(*sp);
- switch (*sp++) {
- int flag;
- case 'n':
- /* decide which type of network based on */
- /* the offset in the config structure */
- if (cp - an->conf ==
- (char *)&conf_proto.atnete-(char *)&conf_proto)
- flag = arouteNet;
- else if (cp - an->conf ==
- (char*)&conf_proto.anetet-(char*)&conf_proto)
- flag = arouteKbox|arouteEtalk;
- else if (cp - an->conf ==
- (char*)&conf_proto.atneta-(char*)&conf_proto)
- flag = arouteKbox;
- else {
- log("%%N at unexpected offset %d, line %d\n",
- cp - an->conf, linenum);
- flag = arouteKbox;
- }
-
- if ((*(short *)cp =
- getanet(flag, an->iaddr)) == 0)
- log("%%N not set, line %d\n", linenum);
- cp += 2;
- an->confsize += 2;
- break;
-
- default:
- log("bad field type %s, linenum %d", st, linenum);
- break;
- }
- break;
-
- case 'i':
- /* IP address name or number */
- iaddr = getiaddr(sp);
- bcopy((caddr_t)&iaddr, cp, sizeof iaddr);
- cp += sizeof iaddr;
- an->confsize += sizeof iaddr;
- break;
-
- case 'l':
- if ((int)cp & 1)
- goto badalign;
- *(long *)cp = htonl(atoii(sp));
- cp += 4;
- an->confsize += 4;
- break;
-
- case 's':
- if ((int)cp & 1)
- goto badalign;
- *(short *)cp = htons(getashort(sp));
- cp += 2;
- an->confsize += 2;
- break;
-
- case 'c':
- *cp = atoii(sp);
- cp++;
- an->confsize++;
- break;
-
- case '"':
- len = strlen(sp) - 1; /* drop trailing " */
- bcopy(sp, cp, len);
- cp += len;
- *cp++ = 0;
- len++;
- an->confsize += len;
- break;
-
- case '\'': /* pascal string */
- len = strlen(sp) - 1; /* drop trailing ' */
- *cp++ = len;
- bcopy(sp, cp, len);
- cp += len;
- len++; /* skip over length field */
- *cp++ = 0;
- len++;
- an->confsize += len;
- break;
-
- default:
- log("bad field type %s, linenum %d",
- st, linenum);
- break;
- }
- continue; /* get next field in line */
- badalign:
- log("long/short bad alignment %s, linenum %d",
- st, linenum);
- break;
- }
- /* get next line */
- }
- /* end of file */
- checkconfigs();
- arouteslen = buildart((struct arouteTuple *)aroutes, sizeof aroutes);
- azoneslen = buildzones(azones, sizeof azones);
- }
-
-
- /*
- * Get next field from 'line' buffer into 'str'. 'linep' is the
- * pointer to current position. No imbeded spaces are allowed in the
- * fields; however, an underscore '_' will convert to a space. (To get
- * a real underscore, double it.)
- */
- getfield(str, len)
- char *str;
- {
- register char *cp = str;
- register und;
-
- for ( ; *linep && (*linep == ' ' || *linep == '\t') ; linep++)
- ; /* skip spaces/tabs */
- if (*linep == 0 || *linep == '#') {
- *cp = 0;
- return;
- }
- und = 0;
- len--; /* save a spot for a null */
- for ( ; *linep && *linep != ' '
- && *linep != '\t' && *linep != '#' ; linep++) {
- if (*linep == '_') {
- if (und) {
- und = 0; cp--; len++;
- } else {
- und++; *linep = ' ';
- }
- } else {
- und = 0;
- }
- *cp++ = *linep;
- if (--len <= 0) {
- *cp = 0;
- log("string truncated: %s, linenum %d", str, linenum);
- return;
- }
- }
- *cp = 0;
- }
-
-
- /*
- * Ascii to integer, with base check.
- */
- atoii(s)
- register char *s;
- {
- int v;
- char *c;
-
- if (isupper(*s))
- *s = tolower(*s);
- if (*s == 'x' || *s == 'h') {
- c = "%x";
- s++;
- } else {
- c = "%d";
- }
- if (sscanf(s, c, &v) != 1)
- log("bad numeric field %s, linenum %d", s, linenum);
- return (v);
- }
-
-
- /*
- * Get an internet address as a hostname or dot format string.
- */
- getiaddr(st)
- register char *st;
- {
- iaddr_t iaddr;
- register struct hostent *host;
-
- if (isdigit(*st)) {
- if ((iaddr = inet_addr(st)) == -1 || iaddr == 0)
- log("bad ipaddress %s, linenum %d", st, linenum);
- } else {
- if ((host = gethostbyname(st)) == 0)
- log("bad hostname %s, linenum %d", st, linenum);
- bcopy(host->h_addr, (caddr_t)&iaddr, sizeof iaddr);
- }
- return (iaddr);
- }
-
-
- /*
- * Get a short number or address.
- */
- getashort(st)
- register char *st;
- {
- register char *cp;
-
- if ((cp = index(st, '.')) == 0)
- return (atoii(st));
- *cp++ = 0;
- return ((atoii(st)<<8) | atoii(cp));
- }
-
-
- /*
- * log an error message
- */
- log(fmt, args)
- char *fmt;
- {
- FILE *fp;
- long time(), tloc;
- struct tm *tm, *localtime();
-
- if (debug)
- fp = stderr;
- else if (scanonly)
- fp = stdout;
- else if ((fp = fopen(atalkalog, "a+")) == NULL)
- return;
- time(&tloc);
- tm = localtime(&tloc);
- fprintf(fp, "%d/%d %02d:%02d ", tm->tm_mon + 1, tm->tm_mday,
- tm->tm_hour, tm->tm_min);
- _doprnt(fmt, &args, fp);
- putc('\n', fp);
- if (fp != stderr && fp != stdout)
- fclose(fp);
- }
-
- /*
- * getanet - scan through the table so far and find an appletalk network
- * number. Called from the %x fields of the config structure
- *
- * flag field:
- * arouteNet - match an IP address, scan for a net route that matches addr
- * arouteKbox - scan for a route using this host
- * arouteKbox|arouteETalk - scan for an Ethertalk net using this host.
- *
- * Limitations: Only one bridge can be configured with a given Ethertalk
- * network number this way. Network numbers referenced must be defined before
- * use.
- */
- getanet(flags, ia)
- iaddr_t ia;
- {
- register int i;
- struct anets *a;
-
- /* Scan table in reverse order - slightly more efficent */
- for(i = nanets-1; i >= 0; --i) {
- a = &anets[i];
-
- if ((flags == arouteNet &&
- ((a->flags & arouteNet) != 0 || (a->flags & arouteHost) != 0) &&
- match_net(a->flags, ia, a->iaddr)) ||
- (flags == arouteKbox &&
- (a->flags & arouteKbox|arouteEtalk) == arouteKbox &&
- a->iaddr == ia) ||
- (flags == arouteKbox|arouteEtalk &&
- (a->flags & flags) == flags &&
- a->iaddr == ia))
- return(a->net);
- }
- log("unable to match appletalk net (%x), line %d\n", flags, linenum);
- return(0);
- }
-
- /*
- * match_net - match a network number, using mask field stored in
- * flags.
- */
- match_net(flags, a1, a2)
- iaddr_t a1, a2;
- {
- return((a1 & node_mask) == (a2 & node_mask));
- }
-
- char *
- hostnameof(ipaddr)
- struct in_addr ipaddr;
- {
- struct hostent *host;
-
- host = gethostbyaddr(&ipaddr.s_addr, sizeof(ipaddr.s_addr), AF_INET);
- if (!host)
- return((char *)inet_ntoa(ipaddr));
- return(host->h_name);
- }
-
- zipinput()
- {
- u_short buf[1000];
- u_short *bp;
- int icount;
- int len;
- u_char *p;
- char *zn;
- int zl;
- struct ZIP zipin;
- struct ZIP *z;
-
- icount = ntohs(aa.count); /* remember incoming count */
- bcopy(aa.stuff, &zipin, sizeof(struct ZIP));
- if (zipin.command != zipQuery || zipin.count == 0)
- return(-1);
- /* get the list of networks */
- bcopy(aa.stuff+sizeof(struct ZIP), buf, zipin.count * sizeof(u_short));
- bp = buf;
- z = (struct ZIP *)aa.stuff;
- z->command = zipReply;
- z->count = 0;
- len = sizeof(struct ZIP);
- for (p = (u_char *)(z+1); len<512&&zipin.count; zipin.count--, bp++) {
- if ((zn = zoneof(*bp)) == NULL)
- continue;
- bcopy(bp, p, sizeof(u_short)); /* copy in network */
- p+= sizeof(u_short); /* move along */
- len+= sizeof(u_short); /* move along */
- zl = *p = strlen(zn); /* get zone length */
- p++; /* bounce */
- len++;
- z->count++;
- bcopy(zn, p, zl); /* copy in zone name */
- p += zl; /* bounce p ...*/
- len += zl; /* ... and len */
- }
- return(len);
- }
-